package com.erlin.common.aop;

import com.alibaba.druid.support.json.JSONUtils;
import com.erlin.common.vo.ResponseVo;
import com.google.common.collect.ImmutableSet;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.util.Objects;
import java.util.Optional;

/**
 * 统一封装controller返回结果
 *
 * @author alin
 */
@RestControllerAdvice
public class ControllerRespAop implements ResponseBodyAdvice<Object> {
//    private static final Set<Class<?>> EXCLUDE = ImmutableSet.of(SignController.class);

    @Override
    public boolean supports(@Nullable MethodParameter methodParameter, @Nullable Class aClass) {
        Class<?> declaringClass = methodParameter.getDeclaringClass();
        //因为是前后端分离，所以这里仅拦截restController  这里后期可以适当调整
        return Objects.nonNull(declaringClass.getAnnotation(RestController.class));
    }

    @Override
    public Object beforeBodyWrite(@Nullable Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (o == null) {
            return ResponseVo.ok(null);
        }
        // 返回值为标准返回对象时, 直接返回
        if (o instanceof ResponseVo) {
            return o;
        }

        // 处理controller返回为string时, 转换报异常的bug
        if (o instanceof String) {
            Optional.ofNullable(serverHttpResponse)
                    .map(HttpMessage::getHeaders)
                    .ifPresent(httpHeaders -> httpHeaders.setContentType(MediaType.APPLICATION_JSON));
            return JSONUtils.toJSONString(ResponseVo.ok(o));
        }

        // pageVo注解修饰的数据统一封装
//        PageVo pageVo = Optional.ofNullable(methodParameter)
//                .map(param -> param.getMethodAnnotation(PageVo.class))
//                .orElse(null);
//        if (o instanceof Number && Objects.nonNull(pageVo)) {
//            return ResponseVo.ok(getPageVo((long) o));
//        }
        // 其他返回对象, 统一封装为标准返回对象
        return ResponseVo.ok(o);
    }

}